#include <iostream>
#include <fstream>
#include <string>
#include "pb_cfg_mount.pb.h"
#include "MsgMount.pb.h"
#include "../mainctrl.h"

int CMountMgr::InitData (CPlayerOnlineData & stOnline, CMountData & stUserMount)
{
    stOnline._uiNowMount = stUserMount._uiNowMount;

    int iIndex = stUserMount.GetMountIndex (stOnline._uiNowMount);
    if (iIndex >= 0)
    {
        stOnline._usNowMountSkillLevel = stUserMount._stMounts[iIndex]._usSkillLevel;
    }
    else
    {
        stOnline._usNowMountSkillLevel = 0;
    }

    return RET_OK;
}

int CMountMgr::LoadConfig(const char* szCfgPath)
{
    int iRet = 0;
    int iIndex = 0;
    if (szCfgPath == NULL)
    {
        CT_ERROR(("Mount Cfg Path is null"));
        return RET_SYSTEM_FAIL;
    }

    pb_cfg_mount stMountCfg;
    std::fstream stFileInput(szCfgPath, std::ios::in | std::ios::binary);
    if (!stMountCfg.ParseFromIstream(&stFileInput))
    {
        CT_ERROR(("Failed to Parse MountCfg!, %s", szCfgPath));
        return RET_SYSTEM_FAIL;
    }

    for (int i = 0; i < stMountCfg.mount_list_rows_size(); ++i)
    {
        const pb_cfg_mount_pb_cfg_mount_list_unit & stMountUnit = stMountCfg.mount_list_rows(i);

        //大于MAX_MOUNT_CFG_COUNT 是前台使用的,后台不用该配置
        if (stMountUnit.id() > MAX_MOUNT_CFG_COUNT)
        {
            continue;
        }

        CMountCfgUnit stCfgUnit;
        stCfgUnit._bHasConfig = false;
        stCfgUnit._usMountId   = stMountUnit.id();
        stCfgUnit._szIconName.Set("%s", stMountUnit.icon().c_str());
        stCfgUnit._bIsMale     = stMountUnit.sex();
        stCfgUnit._ucColor = stMountUnit.color();
        stCfgUnit._usNeedRoleLevel = stMountUnit.level();
        stCfgUnit._ucOutType = stMountUnit.out_type();
        stCfgUnit._iExchangeSoul = stMountUnit.exchange_soule_num();
        stCfgUnit._iDiscardSoul  = stMountUnit.drop_soule_num();

        stCfgUnit._iShowStatus  = stMountUnit.battle_status();

        stCfgUnit._aiBattleStatus.Clear();
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_1());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_2());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_3());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_4());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_5());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_6());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_7());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_8());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_9());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_10());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_11());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_12());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_13());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_14());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_15());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_16());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_17());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_18());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_19());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_20());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_21());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_22());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_23());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_24());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_25());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_26());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_27());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_28());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_29());
        stCfgUnit._aiBattleStatus.AddOneItem(stMountUnit.skill_level_30());

        if (stCfgUnit._iShowStatus > 0)
        {
            iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
                stCfgUnit._iShowStatus);
            if (iIndex < 0)
            {
                CT_WARNING(("unknow status(%d) config",stCfgUnit._iShowStatus));
                CT_RETURN(ERROR_STATUS_EMPTY_CFG);
            }
        }

        for (int j = 0; j < stCfgUnit._aiBattleStatus.Size(); ++j)
        {
            if (stCfgUnit._aiBattleStatus[j] > 0)
            {
                iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
                    stCfgUnit._aiBattleStatus[j]);
                if (iIndex < 0)
                {
                    CT_WARNING(("unknow status(%d) config",
                        stCfgUnit._aiBattleStatus[j]));
                    CT_RETURN(ERROR_STATUS_EMPTY_CFG);
                }
            }
        }

        //本体属性
        std::string sAttrList = stMountUnit.attr_type();
        std::string sAttrAmend = stMountUnit.attr_amend();

        std::vector<std::string> vAttrList;
        std::vector<std::string> vAttrAmend;

        const std::string sDel = ",";
        CTStringUtils::Split(sAttrList, sDel, vAttrList);
        CTStringUtils::Split(sAttrAmend, sDel, vAttrAmend);

        if (vAttrList.size() != vAttrAmend.size())
        {
            CT_ERROR(("%d", stCfgUnit._usMountId));
            return ERROR_MOUNT_CONFIG_INVALID;
        }

        for (unsigned int k = 0; k < vAttrList.size(); k++)
        {
            CAttrPair stPair;
            stPair._ucType = (unsigned char)atoi(vAttrList[k].c_str());
            stPair._iValue = atoi(vAttrAmend[k].c_str());
            stCfgUnit._stAttr.AddOneItem(stPair);
        }

        //阵位属性
        CAttrPair stPair;
        stPair._ucType = (unsigned char)stMountUnit.matrix_attr_type1();
        stPair._iValue = stMountUnit.matrix_attr_amend1();
        stCfgUnit._stMatrixAttr.AddOneItem(stPair);

        stPair._ucType = (unsigned char)stMountUnit.matrix_attr_type2();
        stPair._iValue = stMountUnit.matrix_attr_amend2();
        stCfgUnit._stMatrixAttr.AddOneItem(stPair);

        stPair._ucType = (unsigned char)stMountUnit.matrix_attr_type3();
        stPair._iValue = stMountUnit.matrix_attr_amend3();
        stCfgUnit._stMatrixAttr.AddOneItem(stPair);

        stPair._ucType = (unsigned char)stMountUnit.matrix_attr_type4();
        stPair._iValue = stMountUnit.matrix_attr_amend4();
        stCfgUnit._stMatrixAttr.AddOneItem(stPair);

        stPair._ucType = (unsigned char)stMountUnit.matrix_attr_type5();
        stPair._iValue = stMountUnit.matrix_attr_amend5();
        stCfgUnit._stMatrixAttr.AddOneItem(stPair);

        stPair._ucType = (unsigned char)stMountUnit.matrix_attr_type6();
        stPair._iValue = stMountUnit.matrix_attr_amend6();
        stCfgUnit._stMatrixAttr.AddOneItem(stPair);

        iRet = _stMountCfg.AddConfig(stCfgUnit);
        if (iRet)
        {
            CT_ERROR(("%d, %d", stCfgUnit._usMountId, iRet));
            return iRet;
        }
    }

    //颜色修正必须放到读升级的表格之前
    for (int i = 0; i < stMountCfg.color_offset_rows_size(); ++i)
    {
        const pb_cfg_mount_pb_cfg_color_offset_unit & stCfgUnit = stMountCfg.color_offset_rows(i);

        CMountColorOffset stUnit;
        stUnit._iUpgrade = stCfgUnit.upgrade_offset();
        stUnit._iMatrixAttr = stCfgUnit.matrix_attr();

        iRet = _stMountCfg.AddConfig(stCfgUnit.color(), stUnit);
        if (iRet)
        {
            CT_ERROR(("%d, %d", stCfgUnit.color(), iRet));
            return iRet;
        }
    }

    for (int i = 0; i < stMountCfg.mount_attr_rows_size(); ++i)
    {
        const pb_cfg_mount_pb_cfg_mount_attr_unit & stCfgUnit = stMountCfg.mount_attr_rows(i);

        CMountAttrCfgUnit stUnit;

        //本体属性
        stUnit._stAttr.SetAttr(EXT_ATTR_TURN_ORDRE, stCfgUnit.turn_order());
        stUnit._stAttr.SetAttr(EXT_ATTR_HP, stCfgUnit.hp());
        stUnit._stAttr.SetAttr(EXT_ATTR_PHY_ATK, stCfgUnit.phy_atk());
        stUnit._stAttr.SetAttr(EXT_ATTR_MAG_ATK, stCfgUnit.mag_ack());

        //阵位属性
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_HP, stCfgUnit.matrix_hp());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_MAG_ATK, stCfgUnit.matrix_mag_atk());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_PHY_ATK, stCfgUnit.matrix_phy_atk());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_PHY_DEF, stCfgUnit.matrix_phy_def());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_MAG_DEF, stCfgUnit.matrix_mag_def());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_HIT, stCfgUnit.matrix_hit());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_DODGE, stCfgUnit.matrix_dodge());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_DOUBLE, stCfgUnit.matrix_double());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_ANTI_DOUBLE, stCfgUnit.matrix_anti_double());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_BLOCK, stCfgUnit.matrix_block());
        stUnit._stMatrixAttr.SetAttr(EXT_ATTR_ANTI_BLOCK, stCfgUnit.matrix_anti_block());

        iRet = _stMountCfg.AddAttrConfig(stCfgUnit.level(), stUnit);
        if (iRet)
        {
            CT_ERROR(("%d, %d", stCfgUnit.level(), iRet));
            return iRet;
        }
    }

    for (int i = 0; i < stMountCfg.mount_upgrade_rows_size(); ++i)
    {
        const pb_cfg_mount_pb_cfg_mount_upgrade_unit & stCfgUnit = stMountCfg.mount_upgrade_rows(i);
        CMountUpgradeCfgUnit stUnit;
        stUnit._stNeedSoul[MOUNT_COLOR_GREEN] = stCfgUnit.green();
        stUnit._stNeedSoul[MOUNT_COLOR_BLUE] = stCfgUnit.blue();
        stUnit._stNeedSoul[MOUNT_COLOR_PURPLE] = stCfgUnit.purple();

        iRet = _stMountCfg.AddUpgradeConfig(stCfgUnit.level(), stUnit);
        if (iRet)
        {
            CT_ERROR(("%d, %d", stCfgUnit.level(), iRet));
            return iRet;
        }
    }

    for (int i = 0; i < stMountCfg.hunt_soul_rows_size(); ++i)
    {
        const pb_cfg_mount_pb_cfg_hunt_soul_unit & stCfgUnit = stMountCfg.hunt_soul_rows(i);

        CHuntSoulCfgUnit stUnit;
        stUnit._ucColor = stCfgUnit.color();
        stUnit._iValue = stCfgUnit.value();

        iRet = _stHuntCfg.AddCfgUnit(stCfgUnit.grid(), stUnit);
        if (iRet)
        {
            CT_ERROR(("%d, %d", stCfgUnit.grid(), iRet));
            return iRet;
        }
    }

    for (int i = 0; i < stMountCfg.hunt_rate_rows_size(); i++)
    {
        const pb_cfg_mount_pb_cfg_hunt_rate_unit & stCfgUnit = stMountCfg.hunt_rate_rows(i);

        CRateTarget stDrop;
        stDrop._iTargetID = stCfgUnit.point();
        stDrop._iMaxCount = CRateTarget::TARGET_INFINITY;
        stDrop._iRate = stCfgUnit.rate();

        if (stDrop._iTargetID <= 0 || stDrop._iTargetID > MAX_SILVER_HUNT_SOUL_POINT)
        {
            CT_ERROR(("%d", stDrop._iTargetID));
            return ERROR_MOUNT_CONFIG_INVALID;
        }        

        _stSilverHuntRandom.Add(stDrop);
    }

    //检查配置是否有效
    int iRateSum = _stSilverHuntRandom.GetMax();
    int iTargetCnt = _stSilverHuntRandom.GetTargetCnt();
    if (iRateSum != COMM_MOD || iTargetCnt != MAX_SILVER_HUNT_SOUL_POINT)
    {
        CT_ERROR(("%d, %d", iRateSum, iTargetCnt));
        return ERROR_MOUNT_CONFIG_INVALID;
    }    

    return 0;
}

int CMountMgr::RideMount (CMountData & stMountData, unsigned uiMountId)
{
    int iIndex = stMountData.GetMountIndex(uiMountId);
    if (iIndex < 0)
    {
        return ERROR_MOUNT_NONE;
    }

    stMountData._uiNowMount = uiMountId;
    return 0;
}

int CMountMgr::UnRideMount (CMountData & stMountData)
{
    stMountData._uiNowMount = 0;
    return 0;
}

int CMountMgr::UpgradeMount (unsigned int uiGid, CMountData & stMountData, unsigned int uiMountId, unsigned char ucColor)
{
    int iIndex = stMountData.GetMountIndex(uiMountId);
    if (iIndex < 0)
    {
        return ERROR_MOUNT_NONE;
    }

    CSingleMount & stMount = stMountData._stMounts[iIndex];

    //检查能否升级
    int iTotalSoul = stMountData._iGolden * 10;
    unsigned short usLevel = 0;;
    switch (ucColor)
    {
    case MOUNT_COLOR_GREEN:
        {
            //达到最高级
            usLevel = stMount._usLevel;
            if (usLevel >= MAX_MOUNT_LEVEL)
            {
                return ERROR_MAX_MOUNT_LEVEL;
            }

            iTotalSoul += stMountData._iGreen;
        }
        break;
    case MOUNT_COLOR_BLUE:
        {
            //达到最高级
            usLevel = stMount._usSkillLevel;
            if (usLevel >= MAX_MOUNT_SKILL_LEVEL)
            {
                return ERROR_MAX_MOUNT_LEVEL;
            }

            iTotalSoul += stMountData._iBlue;
        }
        break;
    case MOUNT_COLOR_PURPLE:
        {
            //达到最高级
            usLevel = stMount._usMatrixLevel;
            if (usLevel >= MAX_MOUNT_MATRIX_LEVEL)
            {
                return ERROR_MAX_MOUNT_LEVEL;
            }

            iTotalSoul += stMountData._iPurple;
        }
        break;
    default:
        return ERROR_MOUNT_PARA;
    }

#if 0
    //是否超过主角等级
    short shRoleLevel = 1;
    int iRet = CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleLevel(uiGid, shRoleLevel);
    CHECK_RETURN(iRet);

    if (usLevel >= shRoleLevel)
    {
        return ERROR_GT_MOUNT_LEVEL;
    }
#endif

    if (!_stMountCfg.IsValidLevel (usLevel))
    {
        return ERROR_MOUNT_PARA;
    }

    unsigned char ucMountColor = (unsigned char)_stMountCfg.GetColor((unsigned short)uiMountId);
    int iColorOffset = _stMountCfg.GetUpgradeColorOffset(ucMountColor);

    const CMountUpgradeCfgUnit & stCfg = _stMountCfg.GetUpgradeCfg(usLevel);
    int iNeedSoul = stCfg._stNeedSoul[ucColor] * iColorOffset / COMM_MOD;
    if (iTotalSoul < iNeedSoul)
    {
        return ERROR_LACK_MOUNT_SOUL;
    }

    //修改用户数据
    switch (ucColor)
    {
    case MOUNT_COLOR_GREEN:
        {
            if (stMountData._iGreen >= iNeedSoul)
            {
                stMountData._iGreen -= iNeedSoul;
            }
            else
            {
                stMountData._iGolden -= CT_MAX(1, ((int)ceil((iNeedSoul - stMountData._iGreen) / 10.0)));
                stMountData._iGreen = 0;
            }

            stMount._usLevel += 1;

            if ((20 == stMount._usLevel)
                || (50 == stMount._usLevel)
                || (80 == stMount._usLevel)
                || (100 == stMount._usLevel)
                || (120 == stMount._usLevel)
                || (140 == stMount._usLevel)
                || (150 == stMount._usLevel)
                )
            {
                MsgTips stTips;
                stTips.set_type(1081);
                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(uiGid));
                stTips.add_tip_argument(CTStringUtils::IntToString(stMount._uiMountId));
                stTips.add_tip_argument(CTStringUtils::IntToString(stMount._usLevel));
                CMainCtrl::m_pstMain->SendOnlineTips(stTips);
            }
            

            if (DEF_MOUNT_SKILL_NEED_LEVEL == stMount._usLevel)
            {
                stMount._usSkillLevel = 1;
            }
        }
        break;

    case MOUNT_COLOR_BLUE:
        {
            if (0 == stMount._usSkillLevel)
            {
                return ERROR_MOUNT_SKILL_LOCKED;
            }

            if (stMountData._iBlue >= iNeedSoul)
            {
                stMountData._iBlue -= iNeedSoul;
            }
            else
            {
                stMountData._iGolden -= CT_MAX(1, ((int)ceil((iNeedSoul - stMountData._iBlue) / 10.0)));
                stMountData._iBlue = 0;
            }

            stMount._usSkillLevel += 1;

            if (DEF_MOUNT_MATRIX_NEED_LEVEL == stMount._usSkillLevel)
            {
                stMount._usMatrixLevel = 1;

                {
                    MsgTips stTips;
                    stTips.set_type(1080);
                    stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(uiGid));
                    stTips.add_tip_argument(CTStringUtils::IntToString(stMount._uiMountId));
                    CMainCtrl::m_pstMain->SendOnlineTips(stTips);
                }
            }
        }
        break;

    case MOUNT_COLOR_PURPLE:
        {
            if (0 == stMount._usMatrixLevel)
            {
                return ERROR_MOUNT_MATRIX_LOCKED;
            }

            if (stMountData._iPurple >= iNeedSoul)
            {
                stMountData._iPurple -= iNeedSoul;
            }
            else
            {
                stMountData._iGolden -= CT_MAX(1, ((int)ceil((iNeedSoul - stMountData._iPurple) / 10.0)));
                stMountData._iPurple = 0;
            }

            stMount._usMatrixLevel += 1;
        }
        break;
    }

    if (stMountData._iGolden < 0)
    {
        stMountData._iGolden = 0;
        CT_ERROR(("%d, %d", uiGid, stMountData._iGolden));
    }

    return RET_OK;
}

void CMountMgr::GetMountInfo (CMountData & stMountData, MsgAnsMountOpt & stAns)
{
    stAns.set_opened_pos_num (stMountData._usFreePos);
    stAns.set_now_mount_id (stMountData._uiNowMount);
    stAns.set_green (stMountData._iGreen);
    stAns.set_blue (stMountData._iBlue);
    stAns.set_golden (stMountData._iGolden);
    stAns.set_purple (stMountData._iPurple);

    for (int i = 0; i < stMountData._usFreePos; i++)
    {
        CSingleMount & stUnit = stMountData._stMounts[i];
        if (stUnit._uiMountId > 0)
        {
            MsgSingleMount * pstUnit = stAns.add_mount_bags();
            pstUnit->set_mount_id(stUnit._uiMountId);
            pstUnit->set_bag_pos(i);
            pstUnit->set_mount_grade(stUnit._usLevel);
            pstUnit->set_matrix_grade(stUnit._usMatrixLevel);
            pstUnit->set_skill_grade(stUnit._usSkillLevel);
            pstUnit->set_fight(GetFight (stUnit));
        }
    }
}

int  CMountMgr::UnlockPos (CPlayerBaseInfo & stBaseInfo, CMountData & stMountData)
{
    if (false == stMountData.CanUnlockPos())
    {
        return ERROR_MAX_MOUNT_POS;
    }

    int aiCost[] = {0,0,20,50,100,200,200,200,200, 200};

    int iCost = aiCost[stMountData._usFreePos];

    if (stBaseInfo._iGold < iCost)
    {
        return ERROR_GOLD_LESS;
    }

    CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stBaseInfo, OSS_MONEY_MODULE_47, iCost);

    stMountData._usFreePos += 1;

    return 0;
}

int CMountMgr::CheckAddMount (CMountData & stMountData, unsigned uiMountId)
{
    CMountCfgUnit stCfg;

    int iRet = _stMountCfg.GetConfig(uiMountId, stCfg);
    CHECK_RETURN(iRet);

    iRet = stMountData.CheckAddMount(uiMountId);
    CHECK_RETURN(iRet);

    return RET_OK;
}

int CMountMgr::DiscardMount (CMountData & stMountData, unsigned uiMountId)
{
    int iIndex = stMountData.GetMountIndex (uiMountId);
    if (iIndex < 0)
    {
        return ERROR_MOUNT_NONE;
    }

    if (uiMountId == stMountData._uiNowMount)
    {
        return ERROR_OP_NOW_MOUNT;
    }

    CSingleMount & stMount = stMountData._stMounts[iIndex];

    //退还升级部分的骑魂
    int iRet = TransMountSoul (stMountData, stMount);
    CHECK_RETURN(iRet);
    
    //所有的坐骑都前移
    int iLastMountIndex = stMountData._usFreePos - 1;
    for (int i = iIndex; i <= iLastMountIndex; i++)
    {
        if (i == iLastMountIndex)
        {
            stMountData._stMounts[i].Clear();
        }
        else
        {
            stMountData._stMounts[i] = stMountData._stMounts[i + 1];
        }
    }
    
    ///退回部分骑魂
    CMountCfgUnit stMountCfg;
    iRet = _stMountCfg.GetConfig(uiMountId, stMountCfg);
    if (iRet)
    {
        CT_ERROR(("%d", uiMountId));
    }

    switch (stMountCfg._ucColor)
    {
    case MOUNT_COLOR_GREEN:
        {
            stMountData._iGreen += stMountCfg._iDiscardSoul;
        }
        break;
    case MOUNT_COLOR_PURPLE:
        {
            stMountData._iPurple += stMountCfg._iDiscardSoul;
        }
        break;
    case MOUNT_COLOR_BLUE:
        {
            stMountData._iBlue += stMountCfg._iDiscardSoul;
        }
        break;
    case MOUNT_COLOR_GOLD:
        {
            stMountData._iGolden += stMountCfg._iDiscardSoul;
        }
        break;
    default:
        CT_ERROR(("%d, %d", stMountCfg._ucColor, uiMountId));
    }

    return 0;
}

int CMountMgr::GetFight(CSingleMount& stMount)
{
    CPlayerAttr stAttr;
    int iTempFighting = 0;
    int iTotalFighting = 0;
    int iLeastFighting = 0x7FFFFFFF;
    for (int i = 0; i < MAX_MATRIX_POS; ++i)
    {
        stAttr.Clear();
        iTempFighting = 0;
        GetMountAttr(stMount, i + 1, stAttr);
        CMainCtrl::m_pstMain->m_stRoleMgr.CalcFighting(stAttr, iTempFighting);
        if (iTempFighting > 0 && iLeastFighting > iTempFighting)
        {
            iLeastFighting = iTempFighting;
        }
        iTotalFighting += iTempFighting;
    }

    iTotalFighting -= iLeastFighting;

    iTempFighting = CMainCtrl::m_pstMain->m_stRoleMgr.GetMountFighting(
        stMount._uiMountId, stMount._usSkillLevel);

    return iTotalFighting + iTempFighting;
}

int CMountMgr::GetMountAttr(CSingleMount& stMount, int iPos, CPlayerAttr& stAttr)
{
    //判断坐骑等级和阵位是否合法
    if ((false == _stMountCfg.IsValidLevel(stMount._usLevel))
        || (false == _stMountCfg.IsValidMatrixLevel(stMount._usMatrixLevel))
        || (iPos < 1 && iPos > MOUNT_MATRIX_COUNT))
    {
        return RET_OK;
    }

    CMountCfgUnit stMountCfg;
    int iRet = _stMountCfg.GetConfig(stMount._uiMountId, stMountCfg);
    CHECK_RETURN(iRet);

    //本体属性
    if (stMount._usLevel > 0)
    {
        CMountAttrCfgUnit & stAttrCfg = _stMountCfg.GetAttrCfg(stMount._usLevel);
        for (int i = 0; i < stMountCfg._stAttr.Size(); i++)
        {
            unsigned char ucType = stMountCfg._stAttr[i]._ucType;
            int iValue = stAttrCfg._stAttr.GetAttr(ucType) * stMountCfg._stAttr[i]._iValue / COMM_MOD;
            stAttr.AddAttr(ucType, iValue);
        }
    }

    //阵位属性
    if (stMount._usMatrixLevel > 0)
    {
        CMountAttrCfgUnit & stBaseValue = _stMountCfg.GetAttrCfg(stMount._usMatrixLevel);
        unsigned char ucType = stMountCfg._stMatrixAttr[iPos - 1]._ucType;
        int iPosAmend = stMountCfg._stMatrixAttr[iPos - 1]._iValue;
        int iColorOffSet = _stMountCfg.GetMatrixAttrColorOffset(stMountCfg._ucColor);
        int iBaseValue = stBaseValue._stMatrixAttr.GetAttr(ucType);

        //前后台公式计算顺序必须一致, 否则可能会出现修正偏差
        int iValue =  ((iBaseValue * iColorOffSet / COMM_MOD) * iPosAmend) / COMM_MOD;
        stAttr.AddAttr(ucType, iValue);
    }

    return RET_OK;
}

int CMountMgr::GetMountAttr (CMountData & stMountData, int iPos, CPlayerAttr & stAttr)
{
    stAttr.Clear();

    int iIndex = stMountData.GetMountIndex(stMountData._uiNowMount);
    if (iIndex < 0)
    {
        return RET_OK;
    }

    return GetMountAttr(stMountData._stMounts[iIndex], iPos, stAttr);
}

int CMountMgr::TransMount (CMountData & stMountData, unsigned int uiMountId)
{
    int iIndex = stMountData.GetMountIndex(uiMountId);
    if (iIndex < 0)
    {
        return RET_OK;
    }

    if (uiMountId == stMountData._uiNowMount)
    {
        return ERROR_OP_NOW_MOUNT;
    }

    return TransMountSoul(stMountData, stMountData._stMounts[iIndex]);
}

int CMountMgr::TransMountSoul (CMountData & stMountData, CSingleMount & stMount)
{
    CMountCfgUnit stMountCfg;
    int iRet = _stMountCfg.GetConfig(stMount._uiMountId, stMountCfg);
    CHECK_RETURN(iRet);

    unsigned char ucMountColor = stMountCfg._ucColor;

    //返回绿魂
    if (_stMountCfg.IsValidLevel(stMount._usLevel))
    {
        int iValue = _stMountCfg.GetUpgradeAttrAccumSoul (ucMountColor, stMount._usLevel);

        stMount._usLevel = 1;
        stMountData._iGreen += CT_MAX(0, iValue);
    }
    else
    {
        CT_ERROR(("%d, %d", stMount._usLevel, stMount._uiMountId));
    }

    //返回蓝魂
    if (_stMountCfg.IsValidSkillLevel(stMount._usSkillLevel))
    {
        int iValue = _stMountCfg.GetUpgradeSkillAccumSoul(ucMountColor, stMount._usSkillLevel);

        stMount._usSkillLevel = 0;
        stMountData._iBlue += CT_MAX(0, iValue);
    }
    else
    {
        CT_ERROR(("%d, %d", stMount._usSkillLevel, stMount._uiMountId));
    }

    //返回紫魂
    if (_stMountCfg.IsValidMatrixLevel(stMount._usMatrixLevel))
    {
        int iValue = _stMountCfg.GetUpgradeMatrixAccumSoul (ucMountColor, stMount._usMatrixLevel);

        stMount._usMatrixLevel = 0;
        stMountData._iPurple += CT_MAX(0, iValue);
    }
    else
    {
        CT_ERROR(("%d, %d", stMount._usMatrixLevel, stMount._uiMountId));
    }

    return RET_OK;
}

int CMountMgr::ExChangeMount (unsigned int uiGid, CMountData & stMountData, unsigned int uiMountId)
{
    int iRet = CheckAddMount(stMountData,uiMountId);
    if(iRet)
    {
        CT_ERROR(("%d, %d", iRet, uiMountId));
        return iRet;
    }

    CMountCfgUnit stMountCfg;
    iRet = _stMountCfg.GetConfig((unsigned short)uiMountId, stMountCfg);
    if(iRet)
    {
        CT_ERROR(("%d, %d", iRet, uiMountId));
        return iRet;
    }

    if (stMountCfg._ucOutType != 4)
    {
        return ERROR_MOUNT_EXCHANGE;
    }

    short shRoleLevel = 1;
    iRet = CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleLevel(uiGid, shRoleLevel);
    CHECK_RETURN(iRet);

    if (shRoleLevel < stMountCfg._usNeedRoleLevel)
    {
        return ERROR_MOUNT_OPT_LEVEL;
    }

    int iExchangSoul = stMountCfg._iExchangeSoul;
    switch (stMountCfg._ucColor)
    {
    case MOUNT_COLOR_GREEN:
        {
            if (stMountData._iGreen < iExchangSoul)
            {
                return ERROR_LACK_MOUNT_SOUL;
            }

            stMountData._iGreen -= iExchangSoul;
        }
        break;
    case MOUNT_COLOR_BLUE:
        {
            if (stMountData._iBlue < iExchangSoul)
            {
                return ERROR_LACK_MOUNT_SOUL;
            }

            stMountData._iBlue -= iExchangSoul;
        }
        break;
    case MOUNT_COLOR_PURPLE:
        {
            if (stMountData._iPurple < iExchangSoul)
            {
                return ERROR_LACK_MOUNT_SOUL;
            }

            stMountData._iPurple -= iExchangSoul;
        }
        break;
    case MOUNT_COLOR_GOLD:
        {
            if (stMountData._iGolden < iExchangSoul)
            {
                return ERROR_LACK_MOUNT_SOUL;
            }

            stMountData._iGolden -= iExchangSoul;
        }
        break;

    default:
        CT_ERROR(("%d, %d", stMountCfg._ucColor, uiMountId));
        return ERROR_MOUNT_EXCHANGE;
    }

    stMountData.AddMount(uiMountId);

    return RET_OK;
}

int CMountMgr::HuntSoul (unsigned int uiGid, CMountData & stMountData, int iOpt, MsgAnsMountOpt & stAns)
{
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(uiGid);
    if (iIndex < 0)
    {
        return RET_NO_USER;
    }
    CPlayerBaseInfo& stPlayerBaseInfo = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex];

    int iCount = 0;
    bool bUseGold = false;
    switch (iOpt)
    {
    case 1:
        {
            iCount = CT_MIN(1, (stPlayerBaseInfo._i64Silver / MAX_HUNT_PER_SILVER));
            bUseGold = false;
        }
        break;
    case 2:
        {
            iCount = CT_MIN(MAX_HUNT_BATCH_TIME, (stPlayerBaseInfo._i64Silver / MAX_HUNT_PER_SILVER));
            bUseGold = false;
        }
        break;

    case 3:
        {
            iCount = CT_MIN(1, (stPlayerBaseInfo._iGold / MAX_HUNT_PER_GOLD));
            bUseGold = true;
        }
        break;

    case 4:
        {
            iCount = CT_MIN(MAX_HUNT_BATCH_TIME, (stPlayerBaseInfo._iGold / MAX_HUNT_PER_GOLD));
            bUseGold = true;
        }
        break;

    default:
        return ERROR_MOUNT_PARA;
    }

    if (bUseGold)
    {
        int iMaxResetCount = 0;
        int iRet = CMainCtrl::m_pstMain->m_stVipMgr.GetVipDestNum(stPlayerBaseInfo._chVipLevel, VIP_MODULE_ID_27, iMaxResetCount);
        if (RET_OK != iRet)
        {
            CT_ERROR(("%d, %d, %d", uiGid, stPlayerBaseInfo._chVipLevel, iRet));
            return ERROR_VIP_MODULE;
        }

        if (iMaxResetCount <= stMountData._sGoldHuntCnt.Get(CMainCtrl::m_pstMain->m_iNow, HUNT_RESET_SEC_OF_DAY))
        {
            return ERROR_MOUNT_MAX_HUNT;
        }

        CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_48, (MAX_HUNT_PER_GOLD * iCount));
        stMountData._sGoldHuntCnt.Add(iCount, CMainCtrl::m_pstMain->m_iNow, HUNT_RESET_SEC_OF_DAY);
    }
    else
    {
        CMainCtrl::m_pstMain->m_stItemMgr.SubSilver(stPlayerBaseInfo, (MAX_HUNT_PER_SILVER * iCount), 0);
    }

    while (iCount > 0)
    {
        iCount -= 1;

        int iRet = HuntOnce(stMountData, bUseGold, stAns);
        if (iRet)
        {
            CT_ERROR(("%d, %d, %d", iRet, uiGid, bUseGold));
        }
    }

    return RET_OK;
}

int CMountMgr::HuntOnce (CMountData & stMountData, bool bUseGold, MsgAnsMountOpt & stAns)
{
    int iPos = CT_RANDOM_NUM->GetRand(MAX_HUNT_SOUL_GRID) + 1;

    CHuntSoulCfgUnit stCfg;
    int iRet = _stHuntCfg.GetCfg(iPos, stCfg);
    CHECK_RETURN(iRet);

    int iPoint = 0;
    //金骰猎魂：每次骰子必然投出6点
    if (bUseGold)
    {
        iPoint = 6;
    }
    else
    {
        CRateTarget stDrop;
        iRet = _stSilverHuntRandom.DropOne(stDrop);
        if (iRet)
        {
            CT_ERROR(("%d", iRet));
            iPoint = CT_RANDOM_NUM->GetRand(6) + 1;
        }
        else
        {
            iPoint = stDrop._iTargetID;
        }        
    }

    // 当玩家掷出6点时，必然额外获得2点黄魂
    if (6 == iPoint)
    {
        stMountData._iGolden += 2;
    }

    int iAddValue = iPoint * stCfg._iValue;
    switch (stCfg._ucColor)
    {
    case MOUNT_COLOR_GREEN:
        {
            stMountData._iGreen += iAddValue;
        }
        break;
    case MOUNT_COLOR_BLUE:
        {
            stMountData._iBlue += iAddValue;
        }
        break;
    case MOUNT_COLOR_PURPLE:
        {
            stMountData._iPurple += iAddValue;
        }
        break;
    case MOUNT_COLOR_GOLD:
        {
            stMountData._iGolden += iAddValue;
        }
        break;
    default:
        return ERROR_MOUNT_CONFIG_INVALID;
    }

    MsgHuntResult * pstResult = stAns.add_hunts();
    pstResult->set_pos(iPos);
    pstResult->set_point(iPoint);
    pstResult->set_color(stCfg._ucColor);
    pstResult->set_value(iAddValue);

    return RET_OK;
}

int CMountMgr::GetMountIcon (unsigned short usMountId, CTSizeString<MAX_ICON_NAME_LEN> & stIconName)
{
    CMountCfgUnit stCfg;
    int iRet = _stMountCfg.GetConfig(usMountId, stCfg);
    CHECK_RETURN(iRet);

    stIconName = stCfg._szIconName;

    return RET_OK;
}

int CMountMgr::GetBattleStatus(char chHostType,
        CPlayerOnlineData& stPlayerOnline, CStatusList& stStatusList)
{
    if (GAME_OBJ_TYPE_PLAYER != chHostType &&
        GAME_OBJ_TYPE_PARTNER != chHostType)
    {
        return 0;
    }

    CT_TRACE(("Role(%u) Mount(%u) Skill Level(%d)", stPlayerOnline._uiGID,
        stPlayerOnline._uiNowMount, stPlayerOnline._usNowMountSkillLevel));

    if (stPlayerOnline._uiNowMount <= 0)
    {
        return 0;
    }

    CMountCfgUnit stCfg;
    int iRet = _stMountCfg.GetConfig(stPlayerOnline._uiNowMount, stCfg);
    if (iRet)
    {
        CT_ERROR(("role(%u) get mount(%u) config error(%d)",
            stPlayerOnline._uiGID, stPlayerOnline._uiNowMount, iRet));
        return 0;//避免影响战斗 这里先不出错
    }

    CStatusObj stStatusObj;

    stStatusObj._iAddNum = 1; //叠加层数 这里必须规定正数
    stStatusObj._uiSrcResID = stPlayerOnline._uiNowMount;

    if (stPlayerOnline._usNowMountSkillLevel > 0 &&
        (int)stPlayerOnline._usNowMountSkillLevel <= stCfg._aiBattleStatus.Size())
    {
        //坐骑出场状态
        if (stCfg._iShowStatus > 0)
        {
            stStatusObj._iSrcType = STATUS_SOURCE_OBJ_MOUNT_SHOW;
            stStatusObj._iResID = stCfg._iShowStatus;
            stStatusList._astStatus.AddOneItem(stStatusObj);
            CT_TRACE(("Role(%u) Add Mount(%u) Battle Show Status(%d)",
                stPlayerOnline._uiGID, stStatusObj._uiSrcResID,
                stStatusObj._iResID));
        }

        //坐骑战斗状态
        if (stCfg._aiBattleStatus[stPlayerOnline._usNowMountSkillLevel - 1] > 0)
        {
            stStatusObj._iSrcType = STATUS_SOURCE_OBJ_MOUNT;
            stStatusObj._iResID =
                stCfg._aiBattleStatus[stPlayerOnline._usNowMountSkillLevel - 1];
            stStatusList._astStatus.AddOneItem(stStatusObj);
            CT_TRACE(("Role(%u) Add Mount(%u) Battle Skill Status(%d)",
                stPlayerOnline._uiGID, stStatusObj._uiSrcResID,
                stStatusObj._iResID));
        }
    }

    return 0;
}

bool CMountMgr::HasThisMount (unsigned short usMountID)
{
    return  _stMountCfg.IsValidMount (usMountID);
}

int CMountMgr::GetMountNeedRoleLevel (unsigned short usMountID)
{
    CMountCfgUnit stMountCfg;
    int iRet = _stMountCfg.GetConfig(usMountID, stMountCfg);
    if(iRet)
    {
        return MAX_ROLE_LEVEL + 1;   //坐骑不存在
    }

    return stMountCfg._usNeedRoleLevel;
}

void CMountMgr::AddMountSoul (CMountData & stMountData, CDropItemData & stItemData)
{
    if (ITEM_TYPE_MOUNT_SOUL != stItemData._ucItemType
        || stItemData._iItemCount < 0)
    {
        CT_ERROR(("%d, %d, %d", stItemData._ucItemType, stItemData._usItemConfigID, stItemData._iItemCount));
        return ;
    }
    
    switch (stItemData._usItemConfigID)
    {
    case MOUNT_COLOR_BLUE:
        {
            stMountData._iBlue  += stItemData._iItemCount;
        }
        break;
    case MOUNT_COLOR_GREEN:
        {
            stMountData._iGreen  += stItemData._iItemCount;
        }
        break;
    case MOUNT_COLOR_PURPLE:
        {
            stMountData._iPurple  += stItemData._iItemCount;
        }
        break;
    case MOUNT_COLOR_GOLD:
        {
            stMountData._iGolden  += stItemData._iItemCount;
        }
        break;
    default:
        CT_ERROR(("%d, %d, %d", stItemData._ucItemType, stItemData._usItemConfigID, stItemData._iItemCount));
        break;
    }

    return ;
}
